package cn.lingyangwl.framework.core.response.format;

import cn.lingyangwl.framework.core.response.Resp;
import cn.lingyangwl.framework.tool.core.exception.Assert;
import cn.hutool.core.lang.func.LambdaUtil;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 需要用户自定义并加入到容器中
 * @author shenguangyang
 */
@ToString
public class ResponseFormat {
    /**
     * 日志链路跟踪标识,表示当前请求
     */
    public static String TRACE_ID = "traceId";

    @Getter
    @Setter
    private String codeName;
    /**
     * 值为返回给前端的json对应的success属性名
     */
    @Getter
    @Setter
    private String successName;
    /**
     * 值为返回给前端的json对应的消息属性名
     */
    @Getter
    @Setter
    private String messageName;
    /**
     * 值为返回给前端的json对应的数据属性名
     */
    @Getter
    @Setter
    private String dataName;

    @Getter
    private final ResponseCode responseCode;

    /**
     * 使用原格式 - 请求头标识 <br/>
     * 如果请求头中携带指定的 key - value, 则响应结构为 {@link Resp} 对象的响应结构,
     * 否则为当前对象的指定的响应结构, 当前对象默认也是 {@link Resp} 对象结构, 但是用户
     * 可以自己进行配置的, 可以配置多个请求头, 使用分号隔开
     */
    @Getter
    @Setter
    private String noWrapFormatHeader = "from=inner";

    /**
     * 是否使能http错误码, 如果业务处理失败, 响应状态码为400, 错误不在预期之内, 比如空指针异常, 获取其他未知异常, 则状态码响应500
     */
    @Getter
    @Setter
    private Boolean enableHttpErrorStatus = Boolean.TRUE;

    public static final Map<String, Set<String>> noWrapFormatHeaderMap = new HashMap<>();

    @PostConstruct
    public void init() {
        Arrays.stream(noWrapFormatHeader.split(";")).forEach(e -> {
            String[] split = e.split("=");
            String key = split[0];
            String value = split[1];
            Set<String> data = noWrapFormatHeaderMap.getOrDefault(key, new HashSet<>());
            data.add(value);

            noWrapFormatHeaderMap.put(key, data);
        });
    }

    public ResponseFormat(ResponseCode responseCode) {
        this.responseCode = responseCode;
        Assert.notNull(responseCode, "responseCode is null");
        this.responseCode.check();

        this.codeName = LambdaUtil.getFieldName(Resp<Object>::getCode);
        this.dataName = LambdaUtil.getFieldName(Resp<Object>::getData);
        this.messageName = LambdaUtil.getFieldName(Resp<Object>::getMsg);
        this.successName = LambdaUtil.getFieldName(Resp<Object>::getSuccess);
    }
}
